package com.example.memento.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;

import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 词对象模型
 * 包含词的完整信息，包括多个领域中的含义和解释
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class WordModel {
    
    /**
     * 主词名（用于标识和索引）
     */
    @Size(max = 200, message = "主词名长度不能超过200个字符")
    private String primaryWord;
    
    /**
     * 完整词名列表（包含所有变体形式）
     */

    private List<String> fullWordNames ;
    
    /**
     * 缩写词名列表（包含所有缩写形式）
     */

    private List<String> abbreviatedNames  ;
    
    /**
     * 领域名称列表（存储领域词名称）
     * 用于快速检索该词涉及的所有领域
     */

    private List<String> domainNames  ;
    
    /**
     * 领域词对象列表（存储完整的领域词对象）
     * 包含每个领域中的详细解释信息
     */

    private List<DomainWord> domainWords  ;
    
    /**
     * 词的基本信息
     */
    @Size(max = 500, message = "基本信息长度不能超过500个字符")
    private String basicInfo;
    
    /**
     * 词的通用含义（跨领域的基本含义）
     */
    @Size(max = 2000, message = "通用含义长度不能超过2000个字符")
    private String commonMeaning;
    
    /**
     * 词性（如：名词、动词等）
     */
    @Size(max = 50, message = "词性长度不能超过50个字符")
    private String partOfSpeech;
    
    /**
     * 语言代码（如：zh-CN, en-US）
     */
    @Size(max = 20, message = "语言代码长度不能超过20个字符")
    private String language;
    
    /**
     * 频率/使用频率
     */
    private Integer frequency;
    
    /**
     * 置信度（0.0-1.0）
     */
    private Double confidence;
    
    /**
     * 标签列表
     */
    private List<String> tags;
    
    /**
     * 扩展信息（JSON格式，存储额外的元数据）
     */
    private java.util.Map<String, Object> metadata;
    
    /**
     * 创建时间
     */
    private LocalDateTime createdAt;
    
    /**
     * 更新时间
     */
    private LocalDateTime updatedAt;
    
    /**
     * 添加完整词名
     */
    public void addFullWordName(String wordName) {
        if (fullWordNames == null) {
            fullWordNames = new ArrayList<>();
        }
        if (wordName != null && !wordName.trim().isEmpty() && !fullWordNames.contains(wordName)) {
            fullWordNames.add(wordName);
        }
    }
    
    /**
     * 添加缩写词名
     */
    public void addAbbreviatedName(String abbrevName) {
        if (abbreviatedNames == null) {
            abbreviatedNames = new ArrayList<>();
        }
        if (abbrevName != null && !abbrevName.trim().isEmpty() && !abbreviatedNames.contains(abbrevName)) {
            abbreviatedNames.add(abbrevName);
        }
    }
    
    /**
     * 添加领域词对象
     */
    public void addDomainWord(DomainWord domainWord) {
        if (domainWords == null) {
            domainWords = new ArrayList<>();
        }
        if (domainWord != null && domainWord.hasContent()) {
            domainWord.onCreate();
            domainWords.add(domainWord);
            
            // 同步更新领域名称列表
            if (domainWord.getDomainName() != null && 
                !domainNames.contains(domainWord.getDomainName())) {
                domainNames.add(domainWord.getDomainName());
            }
        }
    }
    
    /**
     * 批量添加领域词对象
     */
    public void addDomainWords(List<DomainWord> domainWords) {
        if (domainWords != null && !domainWords.isEmpty()) {
            domainWords.forEach(this::addDomainWord);
        }
    }
    
    /**
     * 根据领域名称获取领域词对象
     */
    public DomainWord getDomainWord(String domainName) {
        if (domainWords == null || domainName == null) {
            return null;
        }
        return domainWords.stream()
                .filter(dw -> domainName.equals(dw.getDomainName()))
                .findFirst()
                .orElse(null);
    }

    /**
     * 根据领域名称获取领域词对象
     */
    public void addDomainWordName(String domainName) {
        if (domainName == null) {
            return;
        }
        if (domainNames == null ) {
            domainNames = new LinkedList<>();
            domainNames.add(domainName);
        }else {
            if(!domainNames.contains(domainName)){
                domainNames.add(domainName);
                domainNames = domainNames.stream().distinct().toList();
            }
        }
    }


    /**
     * 获取所有领域的所有解释条目
     */
    public List<ExplanationEntry> getAllExplanations() {
        if (domainWords == null || domainWords.isEmpty()) {
            return new ArrayList<>();
        }
        return domainWords.stream()
                .filter(DomainWord::hasContent)
                .flatMap(dw -> dw.getExplanations().stream())
                .collect(Collectors.toList());
    }
    
    /**
     * 获取指定领域的解释条目
     */
    public List<ExplanationEntry> getExplanationsByDomain(String domainName) {
        DomainWord domainWord = getDomainWord(domainName);
        if (domainWord == null || domainWord.getExplanations() == null) {
            return new ArrayList<>();
        }
        return new ArrayList<>(domainWord.getExplanations());
    }
    
    /**
     * 设置创建时间戳
     */
    public void onCreate() {
        if (createdAt == null) {
            createdAt = LocalDateTime.now();
        }
        updatedAt = LocalDateTime.now();
        if (domainWords != null) {
            domainWords.forEach(DomainWord::onCreate);
        }
    }
    
    /**
     * 设置更新时间戳
     */
    public void onUpdate() {
        updatedAt = LocalDateTime.now();
        if (domainWords != null) {
            domainWords.forEach(DomainWord::onUpdate);
        }
    }
    
    /**
     * 检查是否包含指定词名（包括完整词名和缩写）
     */
    public boolean containsWordName(String wordName) {
        if (wordName == null || wordName.trim().isEmpty()) {
            return false;
        }
        
        String lowerWordName = wordName.toLowerCase().trim();
        
        // 检查主词名
        if (primaryWord != null && primaryWord.toLowerCase().equals(lowerWordName)) {
            return true;
        }
        
        // 检查完整词名列表
        if (fullWordNames != null) {
            if (fullWordNames.stream()
                    .anyMatch(name -> name != null && name.toLowerCase().equals(lowerWordName))) {
                return true;
            }
        }
        
        // 检查缩写词名列表
        if (abbreviatedNames != null) {
            if (abbreviatedNames.stream()
                    .anyMatch(name -> name != null && name.toLowerCase().equals(lowerWordName))) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 获取所有词名（包括主词名、完整词名和缩写）
     */
    public List<String> getAllWordNames() {
        List<String> allNames = new ArrayList<>();
        
        if (primaryWord != null && !primaryWord.trim().isEmpty()) {
            allNames.add(primaryWord);
        }
        
        if (fullWordNames != null) {
            allNames.addAll(fullWordNames.stream()
                    .filter(name -> name != null && !name.trim().isEmpty())
                    .collect(Collectors.toList()));
        }
        
        if (abbreviatedNames != null) {
            allNames.addAll(abbreviatedNames.stream()
                    .filter(name -> name != null && !name.trim().isEmpty())
                    .collect(Collectors.toList()));
        }
        
        return allNames.stream().distinct().collect(Collectors.toList());
    }
    
    /**
     * 检查是否有有效内容
     */
    public boolean hasContent() {
        return (primaryWord != null && !primaryWord.trim().isEmpty()) ||
               (fullWordNames != null && !fullWordNames.isEmpty()) ||
               (domainWords != null && !domainWords.isEmpty() && 
                domainWords.stream().anyMatch(DomainWord::hasContent));
    }
    
    /**
     * 获取领域数量
     */
    public int getDomainCount() {
        if (domainWords == null) {
            return 0;
        }
        return (int) domainWords.stream()
                .filter(DomainWord::hasContent)
                .count();
    }
    
    /**
     * 获取总解释条目数量
     */
    public int getTotalExplanationCount() {
        if (domainWords == null || domainWords.isEmpty()) {
            return 0;
        }
        return domainWords.stream()
                .mapToInt(DomainWord::getValidExplanationCount)
                .sum();
    }
}

